import type { Ref } from 'vue'
import { inject } from 'vue'
import _ from 'lodash'
import {
  allViewType,
  EnumAllViewType,
  EnumImgOpType,
  EnumUserActionType,
  opMsgType
} from './imgTypes'
import { useActiveOp } from './hooks/useActiveOp'

interface positionType {
  x: number
  y: number
}

const ScaleFactor = 0.005
const MIN_SCALE = 0.5
const MAX_SCALE = 2
export const useHandlerTouchOrMouseOp = (rect: Ref, viewType: allViewType) => {
  const ws = inject('pyImgHandlerIo') as any

  const {
    activeOp: operationType
  } = useActiveOp()

  let currentScale = 1
  const preMoveStartPosition = {
    x: 0,
    y: 0,
    scale: 1,
    isRecord: false
  }

  let isDown = false
  let currentActionType: EnumUserActionType = EnumUserActionType.none

  const handleMousedown = (e) => {
    console.log('mousedown')
    handleDown(e)
  }
  const handleTouchStart = (e) => {
    console.log('touchstart')
    handleDown(e)
  }
  const handleDown = (e) => {
    isDown = true
    currentActionType = EnumUserActionType.down
    if (operationType.value.type !== EnumImgOpType.measure && operationType.value.type !== EnumImgOpType.performance) {
      return
    }
    const { x, y } = getPosition(e)
    const msg: opMsgType = {
      viewType: viewType,
      opType: operationType.value.type,
      subOpType: operationType.value.subType,
      actionType: currentActionType,
      x,
      y
    }
    ws.sendMsg(msg)
  }

  const handleMousemove = (e: MouseEvent) => {
    handleMove(e)
  }

  const handleTouchmove = (e: TouchEvent) => {
    handleMove(e)
  }

  const handleMove = _.throttle((e: MouseEvent | TouchEvent) => {
    if (isDown) {
      currentActionType = EnumUserActionType.drag
      updateDrag(e)
    } else {
      updateMove(e)
    }
  }, 40)


  const updateMove = (e) => {
    const { x, y } = getPosition(e)
    const msg: opMsgType = {
      viewType: viewType,
      opType: 'getPosition',
      x,
      y
    }

    // ws.sendMsg(msg)
  }

  const updateDrag = (e) => {
    const { x, y } = getPosition(e)
    if (!preMoveStartPosition.isRecord) {
      preMoveStartPosition.x = x
      preMoveStartPosition.y = y
      preMoveStartPosition.isRecord = true
      return
    }
    switch (operationType.value.type) {
      case EnumImgOpType.window:
        handleWindowOp(x, y)
        break
      case EnumImgOpType.pan:
        handlePanOp(x, y)
        break
      case EnumImgOpType.zoom:
        handleScaleOp(x, y)
        break
      case EnumImgOpType.scroll:
        handleScrollOp(x, y)
        break
      case EnumImgOpType.measure:
        handleDrawOp(e)
        break
      case EnumImgOpType.rotate3D:
        handleRotateOp(x, y)
        break
      case EnumImgOpType.performance:
        handleDrawOp(e)
        break
      default:
        break
    }
  }

  const recordPreData = (map: Object) => {
    Object.assign(preMoveStartPosition, map)
  }

  const handleWindowOp = (x, y) => {
    const directionX = x - preMoveStartPosition.x
    const directionY = y - preMoveStartPosition.y
    recordPreData({
      x: x,
      y: y,
      isRecord: true
    })
    const msg: opMsgType = {
      viewType: viewType !== EnumAllViewType.stack ? EnumAllViewType.mpr : EnumAllViewType.stack,
      opType: 'window',
      x: directionX,
      y: directionY
    }
    ws.sendMsg(msg)
  }

  const handlePanOp = (x, y) => {
    const offset_x = x - preMoveStartPosition.x
    const offset_y = y - preMoveStartPosition.y
    recordPreData({
      x: x,
      y: y,
      isRecord: true
    })
    const msg: opMsgType = {
      viewType: viewType,
      opType: 'pan',
      x: offset_x,
      y: offset_y
    }
    ws.sendMsg(msg)
  }
  const handleScaleOp = (x, y) => {
    const directionY = (preMoveStartPosition.y - y) * ScaleFactor
    recordPreData({
      y: y,
      isRecord: true
    })
    const msg: opMsgType = {
      viewType: viewType,
      opType: 'zoom',
      x: x,
      y: y,
      zoom: directionY
    }
    ws.sendMsg(msg)
  }
  const handleScrollOp = (x, y) => {
    if (Math.abs(y - preMoveStartPosition.y) <= 5) {
      return
    }
    const directionY = y - preMoveStartPosition.y > 5 ? 1 : -1
    recordPreData({
      x: x,
      y: y,
      isRecord: true
    })
    const msg: opMsgType = {
      viewType: viewType,
      opType: 'scroll',
      scroll: directionY
    }
    ws.sendMsg(msg)
  }

  const handleMouseup = (e) => {
    console.log('up')
    handleUp(e)
  }

  const handleTouchEnd = (e) => {
    console.log('touch end')
    handleUp(e)
  }

  const handleUp = (e) => {
    isDown = false
    recordPreData({
      x: 0,
      y: 0,
      scale: currentScale,
      isRecord: false
    })
    currentActionType = EnumUserActionType.up
    handleDrawOp(e)
    currentActionType = EnumUserActionType.none
  }
  const handleDrawOp = (e) => {
    const { x, y } = getPosition(e)
    if (operationType.value.type !== 'measure' && operationType.value.type !== 'performance') {
      return
    }
    const msg: opMsgType = {
      viewType: viewType,
      opType: operationType.value.type,
      subOpType: operationType.value.subType,
      actionType: currentActionType,
      x: x,
      y: y
    }
    console.log('drag', viewType)
    ws.sendMsg(msg)
  }

  const handleRotateOp = (x, y) => {
    const deltaY = y - preMoveStartPosition.y
    const deltaX = x - preMoveStartPosition.x
    if (Math.abs(deltaX) <= 5 && Math.abs(deltaY) <= 5) {
      return
    }
    recordPreData({
      x: x,
      y: y,
      isRecord: true
    })
    const msg = {
      viewType: viewType,
      opType: operationType.value.type,
      actionType: currentActionType,
      x: Number.parseFloat((deltaX * 0.2).toFixed(2)),
      y: Number.parseFloat((deltaY * 0.2).toFixed(2))
    }
    console.log(JSON.stringify(msg))
    ws.sendMsg(msg)
  }

  const getPosition = (e: MouseEvent | TouchEvent) => {
    if (e instanceof MouseEvent) {
      const xVal = Math.round(e.clientX - rect.value.left)
      const yVal = Math.round(e.clientY - rect.value.top)
      return {
        x: xVal,
        y: yVal
      }
    } else {
      if (e.targetTouches && e.targetTouches.length > 0) {
        return {
          x: Math.round(e.targetTouches[0].clientX - rect.value.left),
          y: Math.round(e.targetTouches[0].clientY - rect.value.top)
        }
      } else {
        return {
          x: Math.round(e.changedTouches[0].clientX - rect.value.left),
          y: Math.round(e.changedTouches[0].clientY - rect.value.top)
        }
      }
    }
  }

  const handleWheel = (e: any) => {
    const msg: opMsgType = {
      viewType: viewType,
      opType: 'scroll',
      scroll: e.deltaY > 0 ? 1 : -1
    }
    ws.sendMsg(msg)
  }
  return {
    handleMousedown,
    handleMousemove,
    handleMouseup,

    handleTouchStart,
    handleTouchEnd,
    handleTouchmove,
    handleWheel
  }
}
